#![feature(try_trait)]

#[test]
//#[ignore]
fn test0013() {
    let a = [1, 2, 3, 4, 5];
    assert_eq!(a.iter().map(|x| 2 * x).collect::<Vec<i32>>(), [2, 4, 6, 8, 10]);
    let a = ["1", "2", "3", "h"];
    assert_eq!(a.iter().filter_map(|x| x.parse().ok()).collect::<Vec<i32>>(), [1, 2, 3]);
    let a = ['a', 'b', 'c'];
    println!("{:.>15}|{:.>15}|", "index", "value");
    for (i, v) in a.iter().enumerate() {
        println!("{:.>15}|{:.>15}|", i, v.to_uppercase().to_string());
    }
}

#[test]
#[ignore]
fn test0012() {
    fn foo(ref a: i32) {
        println!("{:p}", a);
    }

    foo(2);

    use std::ops::Mul;
    fn square<T: Mul<T, Output=T>>(x: T, y: T) -> T {
        x * y
    }
    assert_eq!(12, square::<u32>(3u32, 4u32));
    assert_eq!(12, square::<i32>(3i32, 4i32));
    assert_eq!(12.0, square::<f64>(3.0, 4.0));

    struct Counter {
        count: usize,
    }

    impl Iterator for Counter {
        type Item = usize;
        fn next(&mut self) -> Option<usize> {
            self.count += 1;
            if self.count < 6 {
                Some(self.count)
            } else {
                None
            }
        }
    }

    let mut c = Counter { count: 0 };
    assert_eq!(Some(1), c.next());
    assert_eq!(Some(2), c.next());
    assert_eq!(Some(3), c.next());
    assert_eq!(Some(4), c.next());
    assert_eq!(Some(5), c.next());
    assert_eq!(None, c.next());
}

#[test]
#[ignore]
fn test0011() {
    #[derive(Debug)]
    struct Circle { x: f64, y: f64, raduis: f64 }
    struct CircleBuilder { x: f64, y: f64, raduis: f64 }

    impl Circle {
        fn area(&self) -> f64 {
            std::f64::consts::PI * self.raduis * self.raduis
        }


        fn new() -> CircleBuilder {
            CircleBuilder { x: 0.0, y: 0.0, raduis: 1.0 }
        }
    }

    impl CircleBuilder {
        fn build(&self) -> Circle {
            Circle { x: self.x, y: self.y, raduis: self.raduis }
        }

        fn x(&mut self, x: f64) -> &mut CircleBuilder {
            self.x = x;
            self
        }

        fn y(&mut self, y: f64) -> &mut CircleBuilder {
            self.y = y;
            self
        }

        fn raduis(&mut self, r: f64) -> &mut CircleBuilder {
            self.raduis = r;
            self
        }
    }

    let x = Circle::new().x(1.0).y(2.0).raduis(3.0).build();
    println!("{:?} area: {}", x, x.area());

    use std::process::Command;
    let x = Command::new("ls").arg("-l").arg("-a").spawn().expect("run fail");
    println!("{:?}", x.wait_with_output());
}

#[test]
#[ignore]
fn test0010() {
    println!("file: {}, line: {}", file!(), line!());

    struct PrintDrop(&'static str);
    impl Drop for PrintDrop {
        fn drop(&mut self) {
            println!("Dropping {}", self.0)
        }
    }

    let _x = PrintDrop("x");
    let _y = PrintDrop("y");
    let _t = (PrintDrop("a"), PrintDrop("b"), PrintDrop("c"));
}

#[test]
#[ignore]
fn test0009() {
    fn double(value: f64) -> f64 { value * 2.0 }
    fn sqrt(value: f64) -> Option<f64> {
        match value.sqrt() {
            x if x.is_normal() => Some(x),
            _ => None,
        }
    }

    let n = 20.0;
    let r = Option::from(n).map(double).and_then(sqrt);
    println!("{:?}", r);

    use std::env;
    use std::fs::File;
    use std::{io, num, fmt};
    use std::io::prelude::*;
    use std::error::Error;
    use std::option::NoneError;

    #[derive(Debug)]
    enum CliError { Io(io::Error), Parse(num::ParseIntError), NoneError(NoneError) }

    impl fmt::Display for CliError {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match *self {
                CliError::Io(ref err) => write!(f, "IO error: {}", err),
                CliError::Parse(ref err) => write!(f, "Parse error: {}", err),
                CliError::NoneError(ref err) => write!(f, "None error: {:?}", err),
            }
        }
    }

    impl Error for CliError {
        fn description(&self) -> &str {
            match *self {
                CliError::Io(ref err) => err.description(),
                CliError::Parse(ref err) => Error::description(err),
                CliError::NoneError(ref _err) => "NoneError",
            }
        }

        fn cause(&self) -> Option<&dyn Error> {
            match *self {
                CliError::Io(ref err) => Some(err),
                CliError::Parse(ref err) => Some(err),
                _ => None,
            }
        }
    }

    impl From<io::Error> for CliError {
        fn from(err: io::Error) -> CliError { CliError::Io(err) }
    }

    impl From<num::ParseIntError> for CliError {
        fn from(err: num::ParseIntError) -> CliError { CliError::Parse(err) }
    }

    impl From<NoneError> for CliError {
        fn from(err: NoneError) -> CliError { CliError::NoneError(err) }
    }

    type ParseResult = Result<i32, CliError>;

    fn run(filename: Option<String>) -> ParseResult {
        let mut file = File::open(filename?)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        let mut sum = 0;
        for c in contents.lines() {
            let n = c.parse::<i32>()?;
            sum += n;
        }
        Ok(sum)
    }

    fn main_() -> Result<(), i32> {
        let filename = env::args().nth(1);
        match run(filename) {
            Ok(n) => {
                println!("{}", n);
                return Ok(());
            }
            Err(_e) => {
                return Err(1);
            }
        }
    }

    main_().unwrap_or_else(|_e| { println!("main error"); });
}

#[test]
#[ignore]
fn test0008() {
    use std::convert::From;
    use std::str::FromStr;
    use std::string::String;
    use std::fmt;

    #[derive(Clone, Debug, PartialEq, Eq)]
    enum Color {
        Red,
        Yellow,
        Blue,
    }

    impl Color {
        fn to_fg_str(&self) -> &str {
            match *self {
                Color::Red => "31",
                Color::Yellow => "33",
                Color::Blue => "32",
            }
        }

        fn to_bg_str(&self) -> &str {
            match *self {
                Color::Red => "41",
                Color::Yellow => "43",
                Color::Blue => "42",
            }
        }
    }

    impl<'a> From<&'a str> for Color {
        fn from(src: &str) -> Self {
            src.parse().unwrap_or(Color::Red)
        }
    }

    impl From<String> for Color {
        fn from(src: String) -> Self {
            src.parse().unwrap_or(Color::Red)
        }
    }

    impl FromStr for Color {
        type Err = ();
        fn from_str(src: &str) -> Result<Self, Self::Err> {
            let src = src.to_lowercase();
            match src.as_ref() {
                "red" => Ok(Color::Red),
                "yellow" => Ok(Color::Yellow),
                "blue" => Ok(Color::Blue),
                _ => Err(()),
            }
        }
    }

////////////////////////////////////////////////////////////////////////////////////////////////

    #[derive(Clone, Debug, PartialEq, Eq)]
    struct ColorString {
        input: String,
        fg_color: Option<Color>,
        bg_color: Option<Color>,
    }

    trait Colorize {
        fn red(self) -> ColorString;
        fn yellow(self) -> ColorString;
        fn blue(self) -> ColorString;
        fn color<S: Into<Color>>(self, color: S) -> ColorString;


        fn on_red(self) -> ColorString;
        fn on_yellow(self) -> ColorString;
        fn on_blue(self) -> ColorString;
        fn on_color<S: Into<Color>>(self, color: S) -> ColorString;
    }

    impl<'a> Colorize for ColorString {
        fn red(self) -> ColorString { self.color(Color::Red) }
        fn yellow(self) -> ColorString { self.color(Color::Yellow) }
        fn blue(self) -> ColorString { self.color(Color::Blue) }
        fn color<S: Into<Color>>(self, color: S) -> ColorString {
            ColorString { fg_color: Some(color.into()), ..self }
        }

        fn on_red(self) -> ColorString { self.on_color(Color::Red) }
        fn on_yellow(self) -> ColorString { self.on_color(Color::Yellow) }
        fn on_blue(self) -> ColorString { self.on_color(Color::Blue) }
        fn on_color<S: Into<Color>>(self, color: S) -> ColorString {
            ColorString { bg_color: Some(color.into()), ..self }
        }
    }

    impl<'a> Colorize for &'a str {
        fn red(self) -> ColorString { self.color(Color::Red) }
        fn yellow(self) -> ColorString { self.color(Color::Yellow) }
        fn blue(self) -> ColorString { self.color(Color::Blue) }
        fn color<S: Into<Color>>(self, color: S) -> ColorString {
            ColorString { fg_color: Some(color.into()), input: String::from(self), ..ColorString::default() }
        }

        fn on_red(self) -> ColorString { self.on_color(Color::Red) }
        fn on_yellow(self) -> ColorString { self.on_color(Color::Yellow) }
        fn on_blue(self) -> ColorString { self.on_color(Color::Blue) }
        fn on_color<S: Into<Color>>(self, color: S) -> ColorString {
            ColorString { bg_color: Some(color.into()), input: String::from(self), ..ColorString::default() }
        }
    }

    impl Default for ColorString {
        fn default() -> Self {
            ColorString {
                input: String::default(),
                fg_color: None,
                bg_color: None,
            }
        }
    }

    impl ColorString {
        fn compute_style(&self) -> String {
            let mut res = String::from("\x1B[");
            let mut has_wrote = false;
            if let Some(ref bgcolor) = self.bg_color {
                if has_wrote { res.push(';') }
                res.push_str(bgcolor.to_bg_str());
                has_wrote = true;
            }
            if let Some(ref fgcolor) = self.fg_color {
                if has_wrote { res.push(';'); }
                res.push_str(fgcolor.to_fg_str());
            }
            res.push('m');
            res
        }
    }

    impl fmt::Display for ColorString {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            let input = &self.input.clone();
            f.write_str(&self.compute_style())?;
            f.write_str(input)?;
            f.write_str("\x1B[0m")?;
            Ok(())
        }
    }

    println!("{}", "hello".red().on_yellow());
    println!("{}", "hello".on_yellow());
    println!("{}", "hello".red());
    println!("{}", "hello".on_yellow().red());
    println!("{}", "hello".red().on_blue());
}

#[test]
#[ignore]
fn test0007() {
    #[derive(Copy, Clone, Debug)]
    struct Book<'a> {
        name: &'a str,
        isbn: i32,
        version: i32,
    }
    let book = Book { name: "Rust编程之道", isbn: 2019060, version: 1 };
    println!("{:?}", book);
    let book2 = Book { version: 2, ..book };
    println!("{:?}", book2);
}

#[test]
#[ignore]
fn test0006() {
    assert_eq!(std::mem::size_of::<&[u32; 5]>(), 8);
    assert_eq!(std::mem::size_of::<&[u32]>(), 16);
    assert_eq!(std::mem::size_of::<()>(), 0);

    fn foo<T>(x: T) -> T { x }
    assert_eq!(foo(1), 1);
    assert_eq!(foo("str"), "str");


    pub trait Fly { fn fly(&self) -> bool; }
    #[derive(Debug)]
    struct Duck;
    impl Fly for Duck {
        fn fly(&self) -> bool { true }
    }
    fn fly_static(s: impl Fly) -> bool { s.fly() }
    fn fly_dyn(s: &dyn Fly) -> bool { s.fly() }
    fn can_fly(s: impl Fly) -> impl Fly {
        if s.fly() {
            println!("can fly");
        } else {
            println!("can not fly");
        }
        s
    }

    let duck = Duck;
    let duck = can_fly(duck);
    assert_eq!(fly_dyn(&duck), true);
    assert_eq!(fly_static(duck), true);

    fn test_copy0<T: Copy>(_i: T) { println!("good") }
    fn test_copy1<T>(_i: T) where T: Copy { println!("good") }
    fn test_copy2(_i: impl Copy) { println!("good") }

    test_copy0(true);
    test_copy1(1);
    test_copy2("str");
    // test_copy("str".to_string());

    let x = "hello".to_string();
    match x.as_ref() {
        "hello" => println!("world"),
        _ => (),
    }

    use std::ops::Deref;
    match x.deref() {
        "hello" => println!("world"),
        _ => (),
    }

    match &*x {
        "hello" => println!("world"),
        _ => (),
    }

    match &x[..] {
        "hello" => println!("world"),
        _ => (),
    }

    use std::borrow::Borrow;
    match x.borrow() {
        "hello" => println!("world"),
        _ => (),
    }

    struct Bird(&'static str);
    trait FlyToHome { fn fly(&self); }
    trait FlyFromHome { fn fly(&self); }
    impl FlyToHome for Bird {
        fn fly(&self) { println!("{} fly to home", self.0); }
    }
    impl FlyFromHome for Bird {
        fn fly(&self) { println!("{} fly From home", self.0); }
    }

    let bird = Bird("poll");
    <Bird as FlyToHome>::fly(&bird);
    <Bird as FlyFromHome>::fly(&bird);
    FlyToHome::fly(&bird);
    FlyFromHome::fly(&bird);
}

#[test]
#[ignore]
fn test0005() {
    // string
    let a = std::str::from_utf8(&[0xe9, 0x81, 0x93]).unwrap();
    assert_eq!("道", a);
    let a = String::from("\u{9053}");
    assert_eq!("道", a);

    // Char
    let tao_u32 = '道' as u32;
    assert_eq!(0x9053, tao_u32);
    println!("U+{:x} {}", tao_u32, '道'.escape_unicode());
    let a = std::char::from_u32(tao_u32);
    println!("{}", a.unwrap());

    let s = "ni你";
    let mut chars = s.chars();
    assert_eq!(Some('n'), chars.next());
    let bytes = s.bytes();
    println!("{},{}", chars.count(), bytes.len());

    // string
    assert_eq!("abc1defXghi".split(|c| c == '1' || c == 'X').collect::<Vec<&str>>(), ["abc", "def", "ghi"]);
    assert_eq!("A.B.".split_terminator('.').collect::<Vec<&str>>(), ["A", "B"]);

    assert_eq!("1abc2abc3".rmatches(char::is_numeric).collect::<Vec<&str>>(), ["3", "2", "1"]);
    assert_eq!("abcXXXabcYYYabc".rmatch_indices("abc").collect::<Vec<_>>(), [(12, "abc"), (6, "abc"), (0, "abc")]);

    assert_eq!("1abc2abc3".trim_matches(char::is_numeric), "abc2abc");

    assert_eq!(4, "4".parse().unwrap());
    assert_eq!(Ok(4), "4".parse::<u32>());

    use std::str::FromStr;
    use std::num::ParseIntError;
    #[derive(Debug, PartialEq)]
    struct Point { x: i32, y: i32 }
    impl FromStr for Point {
        type Err = ParseIntError;
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            let coords = s.trim_matches(|p| p == '{' || p == '}').split(",").collect::<Vec<&str>>();
            let x_fromstr = coords[0].trim().parse::<i32>()?;
            let y_fromstr = coords[1].trim().parse::<i32>()?;
            Ok(Point { x: x_fromstr, y: y_fromstr })
        }
    }

    let p = Point::from_str("{1,2}");
    assert_eq!(p, Ok(Point { x: 1, y: 2 }));

    // format
    println!("{}", format!("|{:5}|", "HelloRust"));
    println!("{}", format!("|{:5.3}|", "HelloRust"));
    println!("{}", format!("|{:10}|", "HelloRust"));
    println!("{}", format!("|{:<12}|", "HelloRust"));
    println!("{}", format!("|{:.<12}|", "HelloRust"));
    println!("{}", format!("|{:>12}|", "HelloRust"));
    println!("{}", format!("|{:^12}|", "HelloRust"));
    println!("{}", format!("|{:=^12}|", "HelloRust"));
    println!("{}", format!("|{:*^12}|", "HelloRust"));
    println!("{}", format!("|{:-^12}|", "HelloRust"));

    println!("{}", format!("|{:+}|", 1234));
    println!("{}", format!("|{:+x}|", 1234));
    println!("{}", format!("|{:+#x}|", 1234));
    println!("{}", format!("|{:b}|", 1234));
    println!("{}", format!("|{:#20b}|", 1234));
    println!("{}", format!("|{:^#20b}|", 1234));
    println!("{}", format!("|{:=^#20b}|", 1234));

    println!("{}", format!("|{:.4}|", std::f64::consts::PI));
    println!("{}", format!("|{:.2}|", std::f64::consts::PI));
    println!("{}", format!("|{:<10.4}|", std::f64::consts::PI));
    println!("{}", format!("|{:#^12.2}|", std::f64::consts::PI));
    println!("{}", format!("|{:e}|", std::f64::consts::PI));

    let s = r"1234
                    5678
                    9876
                    4321";
    let (mut x, mut y) = (0, 0);
    for (i, v) in s.lines().enumerate() {
        println!("{:?}", (i, v.trim()));
        let a = v.trim().get(i..i + 1).unwrap().parse::<u32>().unwrap();
        let b = v.trim().get(3 - i..3 - i + 1).unwrap().parse::<u32>().unwrap();
        x += a;
        y += b;
    }
    assert_eq!(38, x + y);
}

#[test]
#[ignore]
fn test0004() {
    // trait
    struct Duck;
    struct Pig;
    trait Fly { fn fly(&self) -> bool; }

    impl Fly for Duck {
        fn fly(&self) -> bool { true }
    }

    impl Fly for Pig {
        fn fly(&self) -> bool { false }
    }

    fn fly_static<T: Fly>(s: T) -> bool {
        s.fly()
    }

    fn fly_dyn(s: &dyn Fly) -> bool {
        s.fly()
    }

    let pig = Pig;
    assert_eq!(false, fly_static::<Pig>(pig));
    let duck = Duck;
    assert_eq!(true, duck.fly());
    assert_eq!(true, fly_static::<Duck>(duck));
    assert_eq!(false, fly_dyn(&Pig));
    assert_eq!(true, fly_dyn(&Duck));

    struct Point { x: f64, y: f64 }
    impl std::fmt::Debug for Point {
        fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
            write!(f, "x: {}, y: {}", self.x, self.y)
        }
    }
    let a = Point { x: 1.0, y: 2.0 };
    println!("{:?}", a);

    // Result
    let x: Result<i32, &str> = Ok(-1);
    assert_eq!(x.is_ok(), true);
    let x: Result<i32, &str> = Err("err");
    assert_eq!(x.is_err(), true);
}

#[test]
#[ignore]
fn test0003() {
    // smart pointer
    #[derive(PartialEq, Debug)]
    struct Point { x: f64, y: f64 }
    let a = Box::new(Point { x: 1.0, y: 2.0 });
    let b = *a;
    assert_eq!(b, Point { x: 1.0, y: 2.0 });
}

#[test]
#[ignore]
fn test0002() {
    // Vector
    let mut a = vec![];
    a.push(1);
    a.push(2);
    assert_eq!(a, [1, 2]);
    let a = vec![1; 10];
    assert_eq!(1, a[3]);
    let mut a = Vec::new();
    a.push(100);
    assert_eq!(None, a.get(1));

    // DequeVec
    use std::collections::VecDeque;
    let mut buf = VecDeque::new();
    buf.push_front(1);
    buf.push_back(2);
    buf.push_front(0);
    buf.push_back(3);
    assert_eq!(Some(&3), buf.get(3));
    println!("{:?}", buf);

    // List
    use std::collections::LinkedList;
    let mut list = LinkedList::new();
    list.push_back(1);
    list.push_back(2);
    let mut tend = LinkedList::new();
    tend.push_back(3);
    tend.push_back(4);
    list.append(&mut tend);
    println!("{:?}", list);

    // HashMap
    use std::collections::HashMap;
    let mut a = HashMap::new();
    a.insert(1, "c");
    a.insert(10, "d");
    println!("{:?}", a);
    assert_eq!(Some(&"c"), a.get(&1));

    use std::collections::BTreeMap;
    let mut a = BTreeMap::new();
    a.insert(1, "1");
    a.insert(10, "10");
    a.insert(100, "100");
    println!("{:?}", a);
    assert_eq!(Some(&"100"), a.get(&100));

    // HashSet
    use std::collections::HashSet;
    let mut a = HashSet::new();
    a.insert("1");
    a.insert("10");
    a.insert("100");
    a.insert("10");
    println!("Set: {:?}", a);

    // BinaryHeap
    use std::collections::BinaryHeap;
    let mut a = BinaryHeap::new();
    a.push(1000);
    a.push(10);
    a.push(100);
    a.push(1);
    println!("Before: {:?}", a);
    a.pop();
    println!("After: {:?}", a);
    a.pop();
    println!("After: {:?}", a);
}

#[test]
#[ignore]
fn test0001() {
    //tuple
    let fun = |x: (i32, i32)| { return (x.0 + 1, x.1 + 1); };
    assert_eq!((2, 2), fun((1, 1)));
    let t = ("hello", 1, '我');
    println!("{},{},{}", t.0, t.1, t.2);

    //struct
    struct People {
        name: &'static str,
        gender: u32,
    }
    impl People {
        fn new(n: &'static str, g: u32) -> Self {
            People { name: n, gender: g }
        }

        fn name(&self) {
            println!("{}", self.name);
        }

        fn set_name(&mut self, n: &'static str) {
            self.name = n;
        }

        fn gender(&self) {
            let gender = if self.gender == 1 { "boy" } else { "girl" };
            println!("gender: {}", gender);
        }
    }

    let alex = People::new("Alex", 1);
    alex.name();
    alex.gender();

    let mut alici = People::new("Alici", 0);
    alici.name();
    alici.set_name("Alice");
    alici.name();
    alici.gender();

    struct Color(i32, i32, i32);
    let c = Color(1, 2, 3);
    assert_eq!(1, c.0);

    struct Integer(u32);
    let i = Integer(10);
    assert_eq!(i.0, 10);

    type Int = i32;
    let j: Int = 20;
    assert_eq!(20, j);

    struct Empty;
    let x = Empty;
    let y = Empty;
    println!("x: {:p}", &x);
    println!("y: {:p}", &y);

    assert_eq!((..), std::ops::RangeFull);

    //enum
    #[allow(dead_code)]
    enum Number { Zero, One, Two }
    let a = Number::One;
    let x = match a {
        Number::Zero => "zero",
        Number::One => "one",
        Number::Two => "two",
    };
    println!("{}", x);

    #[allow(dead_code)]
    enum ColorValue { Red = 0xff0000, Green = 0x00ff00, Blue = 0x0000ff }
    let g = ColorValue::Green;
    println!("#{:06x}", g as u32);

    #[derive(Debug)]
    enum IpAddr { V4(u8, u8, u8, u8), V6(String) }
    let x = IpAddr::V4(192, 168, 0, 1);
    let y = IpAddr::V6(String::from("1.2.3.4.5.6"));
    println!("{:?}", (x, y));

    let a = &Some("hello".to_string());
    match a {
        Some(i) => println!("{}", i),
        None => println!("None"),
    }
}

#[test]
#[ignore]
fn test0000() {
    // while let
    let mut v = vec![1, 2, 3, 4, 5];
    while let Some(a) = v.pop() {
        print!("{}", a);
    }
    println!();

    // basic type
    println!("true:{}, false:{}", true as i32, false as i8);
    assert_eq!(-3.14, -3.14f64);
    println!("{:?}, {:?}, {:?}", std::f32::INFINITY, std::f32::NEG_INFINITY, std::f32::NAN);
    println!("{:?}, {:?}", std::f32::MIN, std::f32::MAX);

    // Array
    let a: [i32; 3] = [1, 2, 3];
    assert_eq!(3, a.len());
    let mut a = [1, 2, 3];
    a[0] = 10;
    assert_eq!(10, a[0]);
    assert_eq!(Some(&3), a.get(2));

    // Range
    assert_eq!((1..5), std::ops::Range { start: 1, end: 5 });
    for i in 1..5 {
        print!("{}", i);
    }
    println!();
    for i in 1..=5 {
        print!("{}", i);
    }
    println!();

    // slice
    let a = [1, 2, 3, 4, 5];
    assert_eq!(&a, &[1, 2, 3, 4, 5]);
    assert_eq!(&a[1..], &[2, 3, 4, 5]);
    assert_eq!(&a[1..], [2, 3, 4, 5]);
    assert_eq!(a[1..], [2, 3, 4, 5]);

    //string
    let truth = "Rust是一门优雅的语言";
    let ptr = truth.as_ptr();
    let len = truth.len();
    assert_eq!(28, len);
    let slice = unsafe {
        std::slice::from_raw_parts(ptr, len)
    };
    let s = std::str::from_utf8(slice);
    assert_eq!(s, Ok(truth));
    println!("size: {}", truth.chars().count());

    //pointer
    let mut x = 10;
    let px = &mut x as *mut i32;
    let y = Box::new(20);
    let py = &*y as *const i32;
    unsafe { *px += *py; }
    assert_eq!(x, 30);

    //never type
    #[allow(dead_code)]
    fn foo() -> i32 {
        #[allow(unused_variables)]
            let x = {
            return 123;
        };
    }
    // #[allow(unused_variables)]
    // let a = panic!("Nothing!");
}

fn main() {
    println!("Hello, world!");
}
